﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.ComponentModel;
using Engine.Attributes;

namespace Engine
{
	/// <summary>
	/// Non-generics-based interface to Connection<T>
	/// </summary>
	public interface IConnection
	{
		/// <summary>
		/// Gets the tail of the connection as an IInPort
		/// </summary>
		IInPort Tail { get; }

		/// <summary>
		/// Gets the head of the connection as an IOutPort
		/// </summary>
		IOutPort Head { get; }

		/// <summary>
		/// 
		/// </summary>
		/// <returns>Returns the generic type (the type of data carried by this IConnection)</returns>
		Type GetGenericType();
	}

	/// <summary>
	/// Instance of a one-to-one link between an OutPort and an InPort.
	/// </summary>
	public class Connection<T>: IConnection
	{
        /// <summary>
        /// Producer port to which this Connection is attached
        /// </summary>
        public Port<T> HeadPort { get; private set; }

        /// <summary>
        /// Consumer port to which this Connection is attached
        /// </summary>
        public Port<T> TailPort { get; private set; }

        /// <summary>
        /// Creates a new connection
        /// </summary>
        /// <param name="headPort">Port supplying data to this Connection</param>
        /// <param name="tailPort">Port receiving data from this Connection</param>
        public Connection(Port<T> headPort, Port<T> tailPort)
		{
            this.HeadPort = headPort;
            this.TailPort = tailPort;
		}

        public void Send(T msg)
        {
            TailPort.Value = msg;
        }

		#region IConnection Members

		public IInPort Tail
		{
			get { return (IInPort)this.TailPort; }
		}

		public IOutPort Head
		{
			get { return (IOutPort)this.HeadPort; }
		}

		public Type GetGenericType()
		{
			return this.GetType().GetGenericArguments()[0];
		}

		#endregion
	}
}
